<?php
/**
 *
 *
 */
abstract class Yz_Module_WebModule
    extends Yz_Module_Abstract
    implements Yz_Module_WebModule_Interface
{

    const DEFAULT_CONTROLLER = "Default";
    const ERROR_CONTROLLER = false;


    /** try to find a controller specified by a string convertible to an identifier
     *      (@see Yz_String::identifier)
     *  @return string|bool(false)
     */
    public function hasController($controllerName)
    {
        debug($controllerName);
        $name = Yz_String::testNotEmpty($controllerName, 'controller name');
        return $this->resolve( 'Controller_' . ucfirst($controllerName), $throw=false );
    }

    /** find a controller by exact name
     *  @return Yz_Controller_Interface&
     *  @throws Yz_Module_Exception_ControllerNotFound
     */
    public function selectController($controllerName)
    {
        debug($controllerName);
        $class = $this->hasController($controllerName);
        if (false === $class) {
            throw Yz_Module_Exception_ControllerNotFound::_new(array(
                'moduleName' => $this->fullName,
                'ctrlName' => $controllerName,
            )) ;
        }
        assert('is_subclass_of($class,"Yz_Controller_Interface")');
        return new $class($this);
    }



    /** Select a default controller (usually, when a named controller not found)
     *      It may be an error controller ("controller $name not found")
     *      or module contents generator
     *      or a dispatcher
     *  @return Yz_Controller_Interface&
     *  @todo if DEFAULT_CONTROLLER is false, throw SmthNotFound => 404
     *  @throws Yz_Module_Exception_ClassNotFound
     *      because having specified a DEFAULT_CONTROLLER one assumed that it exists
     */
    public function selectDefaultController()
    {
        $default = static::DEFAULT_CONTROLLER;
        if (! $default) {
            throw new Yz_Exception_NotImplemented();
        }
        $class = $this->resolve( 'Controller_' . $default, $throw=true );
        assert('is_subclass_of($class,"Yz_Controller_Interface")');
        return new $class($this);
    }

    public function selectErrorController()
    {
        $default = static::ERROR_CONTROLLER;
        if (! $default) {
            return false;
        }
        $class = $this->resolve( 'Controller_' . $default, $throw=true );
        assert('is_subclass_of($class,"Yz_Controller_Interface")');
        return new $class($this);
    }

    /** select a template by name
     *  @return Yz_Controller_Interface&
     *  @throws TemplateNotFound
     */
    public function selectTemplate($templateName)
    {
        debug($templateName);

        // regardless of what $templateName is supplied, it must match a class
        $name = Yz_String::testNotEmpty($templateName, 'template name');
        $class = $this->resolve( 'Template_' . ucfirst($name), $throw=false );
        if (false === $class) {
            throw Yz_Module_Exception_TemplateNotFound::_new(array(
                'templateName' => $name,
                'moduleName' => $this->fullName,
            ));
        }
        assert('is_subclass_of($class,"Yz_Template_Interface")');
        return new $class($this);
    }

} // class
